package no21.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * CountDownLatch演示
 * 
 * @author gao
 * 
 */

class Driver {
	// 第一个类是一个启动信号，在 driver 为继续执行 worker 做好准备之前，它会阻止所有的 worker 继续执行。
	// 第二个类是一个完成信号，它允许 driver 在完成所有 worker 之前一直等待。
	void main() throws InterruptedException {
		// 通过锁存器控制所有线程
		CountDownLatch startSignal = new CountDownLatch(1);
		CountDownLatch doneSignal = new CountDownLatch(10);

		// create and start threads
		// 启动所有线程
		for (int i = 0; i < 10; ++i)
			new Thread(new Worker(startSignal, doneSignal)).start();

		// doSomethingElse(); // don't let run yet
		// 使当前线程在锁存器倒计数至零之前一直等待
		startSignal.countDown(); // let all threads proceed
		// doSomethingElse();
		// doneSignal 主线程等待所有线程结束
		doneSignal.await(); // wait for all to finish
	}
}

class Worker implements Runnable {
	private final CountDownLatch startSignal;
	private final CountDownLatch doneSignal;

	Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
		this.startSignal = startSignal;
		this.doneSignal = doneSignal;
	}

	public void run() {
		try {
			// 使用startSignal锁存器,让线程等待
			startSignal.await();
			doWork();
			// 告诉 doneSignal 计数减1
			doneSignal.countDown();
		} catch (InterruptedException ex) {
		} // return;
	}

	void doWork() {
	}
}

class Driver2 { // ...
	void main() throws InterruptedException {
		CountDownLatch doneSignal = new CountDownLatch(10);
		Executor e = Executors.newCachedThreadPool();

		for (int i = 0; i < 10; ++i)
			// create and start threads
			e.execute(new WorkerRunnable(doneSignal, i));
		
		//主线程等待所以线程执行完成
		doneSignal.await(); // wait for all to finish
	}
}

class WorkerRunnable implements Runnable {
	private final CountDownLatch doneSignal;
	private final int i;

	WorkerRunnable(CountDownLatch doneSignal, int i) {
		this.doneSignal = doneSignal;
		this.i = i;
	}

	public void run() {
		doWork(i);//子线程执行自己的任务
		doneSignal.countDown();//告诉锁存在器 计数减1
	}

	void doWork(int i) {
	}
}

public class CountDownLatchDemo {

}